package com.learn.demo.ws;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.learn.demo.config.ApplicationContextProvider;
import com.learn.demo.config.GetHttpSessionConfig;
import com.learn.demo.pojo.Message;
import com.learn.demo.service.MessageService;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.sql.Timestamp;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

@ServerEndpoint(value = "/chat", configurator = GetHttpSessionConfig.class)
@Component
public class ChatEndPoint {

    private static final Map<String, Session> onlineUser = new ConcurrentHashMap<>();
    private MessageService messageService;

    @OnOpen
    public void onOpen(Session session, EndpointConfig endpointConfig) throws IOException {
        if (messageService == null) {
            messageService = ApplicationContextProvider.getApplicationContext().getBean(MessageService.class);
        }

        String username = (String) endpointConfig.getUserProperties().get("username");
        if (username != null) {
            session.getUserProperties().put("username", username); // 将用户名存储在 Session 用户属性中
            onlineUser.put(username, session);

            // 发送最近10条历史消息
            sendRecentMessages(session);

            // 广播新用户加入消息
            broadcastSystemMessage(username + "来了！", username);
        }
    }

    private void sendRecentMessages(Session session) throws IOException {
        QueryWrapper<Message> queryWrapper = new QueryWrapper<>();
        queryWrapper.orderByAsc("time").last("LIMIT 10");

        List<Message> recentMessages = messageService.list(queryWrapper);
        for (Message msg : recentMessages) {
            JSONObject msgJson = new JSONObject();
            msgJson.put("type", "history");
            msgJson.put("username", msg.getUsername());
            msgJson.put("message", msg.getText());
            msgJson.put("timestamp", msg.getTime().toString());

            session.getBasicRemote().sendText(msgJson.toJSONString());
        }
    }

    private void broadcastSystemMessage(String systemMessage, String excludeUsername) throws IOException {
        JSONObject jsonMessage = new JSONObject();
        jsonMessage.put("type", "broad");
        jsonMessage.put("message", systemMessage);

        broadcastAllUsers(jsonMessage.toJSONString(), excludeUsername);
    }

    private void broadcastAllUsers(String message, String senderUsername) throws IOException {
        Set<Map.Entry<String, Session>> entries = onlineUser.entrySet();
        for (Map.Entry<String, Session> entry : entries) {
            String receiverUsername = entry.getKey();
            Session session = entry.getValue();

            // 不发送给自己
            if (!senderUsername.equals(receiverUsername)) {
                session.getBasicRemote().sendText(message);
            }
        }
    }

    @OnMessage
    public void onMessage(String message, Session session) throws IOException {
        String currentUsername = (String) session.getUserProperties().get("username");

        JSONObject jsonMessage = JSON.parseObject(message);
        jsonMessage.put("time", new Timestamp(System.currentTimeMillis()).toString()); // 添加当前时间戳
        jsonMessage.put("type", "chat");

        // 保存消息到数据库
        saveMessageToDatabase(jsonMessage);

        // 广播消息给所有用户
        broadcastAllUsers(jsonMessage.toJSONString(), currentUsername);
    }

    private void saveMessageToDatabase(JSONObject jsonMessage) {
        Message m = Message.builder()
                .username(jsonMessage.getString("username"))
                .text(jsonMessage.getString("message"))
                .time(new Timestamp(System.currentTimeMillis())) // 使用当前时间
                .build();
        boolean result = messageService.save(m);

        if (result) {
            System.out.println("消息保存成功");
        } else {
            System.out.println("消息保存失败");
        }
    }

    @OnClose
    public void onClose(Session session) {
        String username = (String) session.getUserProperties().get("username");
        if (username != null) {
            onlineUser.remove(username);
            try {
                broadcastSystemMessage(username + "走了！", username);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
